package demo.Map;

import java.util.*;

/**
 * 自定义元素排序
 */
public class TreeMapSort {
    /**
     * 注意：Set的元素不可重复，Map的键不可重复，如果存入重复元素如何处理
     *
     * Set元素重复元素不能存入add方法返回false
     *
     * Map的重复健将覆盖旧键，将旧值返回。
     * @param args
     */
    public static void main(String[] args) {
        TreeMap<Person, String> hm = new TreeMap<Person, String>(
                new MyComparator());
        hm.put(new Person("jack", 20), "1001");
        hm.put(new Person("rose", 18), "1002");
        hm.put(new Person("lucy", 19), "1003");
        hm.put(new Person("hmm", 17), "1004");
        hm.put(new Person("ll", 25), "1005");
        System.out.println(hm);
        System.out.println(hm.put(new Person("rose", 18), "1006"));

        Set<Map.Entry<Person, String>> entrySet = hm.entrySet();
        Iterator<Map.Entry<Person, String>> it = entrySet.iterator();
        while (it.hasNext()) {
            Map.Entry<Person, String> next = it.next();
            Person key = next.getKey();
            String value = next.getValue();
            System.out.println(key + " = " + value);
        }
    }
}

/**
 * Comparator
 * Comparator是一个FunctionalInterface，需要实现compare方法：
 *
 * int compare(T o1, T o2);
 *
 * Comparator在java.util包中，代表其是一个工具类，用来辅助排序的。
 *
 * 在讲Comparable的时候，我们提到Comparable指定了对象的natural ordering，如果我们在添加到可排序集合类的时候想按照我们自定义的方式进行排序，这个时候就需要使用到Comparator了。
 *
 * Collections.sort(List,Comparator),Arrays.sort(Object[],Comparator) 等这些辅助的方法类都可以通过传入一个Comparator来自定义排序规则。
 *
 * 在排序过程中，首先会去检查Comparator是否存在，如果不存在则会使用默认的natural ordering。
 *
 * 还有一个区别就是Comparator允许对null参数的比较，而Comparable是不允许的，否则会爬出NullPointerException。
 * ————————————————
 * 原文链接：https://blog.csdn.net/superfjj/article/details/105898913
 */
class MyComparator implements Comparator<Person> {

    @Override
    public int compare(Person p1, Person p2) {
        if (p1.getAge() > p2.getAge()) {
            return -1;
        } else if (p1.getAge() < p2.getAge()) {
            return 1;
        }
        return p1.getName().compareTo(p2.getName());
    }

}

/**
 * Comparable是java.lang包下面的接口，lang包下面可以看做是java的基础语言接口。
 *
 * 实际上Comparable接口只定义了一个方法：
 *
 *  public int compareTo(T o);
 *
 * 实现这个接口的类都需要实现compareTo方法，表示两个类之间的比较。
 *
 * 这个比较排序之后的order，按照java的说法叫做natural ordering。这个order用在一些可排序的集合比如：SortedSet，SortedMap等等。
 *
 * 当使用这些可排序的集合添加相应的对象时，就会调用compareTo方法来进行natural ordering的排序。
 *
 * 几乎所有的数字类型对象：Integer, Long，Double等都实现了这个Comparable接口。
 * ————————————————
 * 原文链接：https://blog.csdn.net/superfjj/article/details/105898913
 */
class Person implements Comparable<Person> {
    private String name;
    private int age;

    Person() {

    }

    public Person(String name, int age) {

        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public int hashCode() {

        return this.name.hashCode() + age * 37;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Person) {
            Person p = (Person) obj;
            return this.name.equals(p.name) && this.age == p.age;
        } else {
            return false;
        }
    }

    @Override
    public String toString() {

        return "Person@name:" + this.name + " age:" + this.age;
    }

    @Override
    public int compareTo(Person p) {

        if (this.age > p.age) {
            return 1;
        } else if (this.age < p.age) {
            return -1;
        }
        return this.name.compareTo(p.name);
    }

}
